package com.cans.lightning.business.lowcode.service.impl;

import com.cans.lightning.base.mapper.IBaseMapper;
import com.cans.lightning.base.service.impl.BaseServiceImpl;
import com.cans.lightning.business.core.utils.ContextUtil;
import com.cans.lightning.business.lowcode.dao.AppTableDao;
import com.cans.lightning.business.lowcode.dto.AppTableDto;
import com.cans.lightning.business.lowcode.dto.AppTableFieldDto;
import com.cans.lightning.business.lowcode.entity.AppTable;
import com.cans.lightning.business.lowcode.enums.TableTypeEnum;
import com.cans.lightning.business.lowcode.manager.AppIndexManager;
import com.cans.lightning.business.lowcode.mapper.AppTableMapper;
import com.cans.lightning.business.lowcode.service.api.IAppTableFieldService;
import com.cans.lightning.business.lowcode.service.api.IAppTableService;
import com.cans.lightning.business.lowcode.service.api.IDBTableOperatorService;
import com.google.common.collect.Lists;
import org.beetl.sql.mapper.BaseMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 表单下的表信息
 *
 * @author shencan
 * @date 2020/6/14 20:53
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class AppTableServiceImpl extends BaseServiceImpl<AppTable, AppTableDto, String> implements IAppTableService {

    @Resource
    private AppTableDao appTableDao;
    @Resource
    private AppTableMapper appTableMapper;
    @Resource
    private IAppTableFieldService appTableFieldService;
    @Resource
    private AppIndexManager appIndexManager;
    @Resource(name = "dBTableOperatorService")
    private IDBTableOperatorService dbTableOperatorService;

    @Override
    public BaseMapper<AppTable> getDaoImpl() {
        return appTableDao;
    }

    @Override
    public IBaseMapper<AppTable, AppTableDto, String> getMapperImpl() {
        return appTableMapper;
    }

    @Override
    public List<AppTable> findByFormId(String formId) {
        return appTableDao.createLambdaQuery().andEq(AppTable::getFormId,formId).select();
    }

    @Override
    public List<AppTableDto> getInfoByFormId(String formId) {
        List<AppTable> appTableList = appTableDao.createLambdaQuery().andEq(AppTable::getFormId, formId).select();
        List<AppTableFieldDto> tableFieldDtoList = appTableFieldService.getByTableIds(appTableList.stream().map(AppTable::getId).collect(Collectors.toList()));
        Map<String, List<AppTableFieldDto>> tableFieldMap = tableFieldDtoList.stream().collect(Collectors.groupingBy(AppTableFieldDto::getTableId));
        List<AppTableDto> resList = Lists.newArrayList();
        for (AppTable appTable : appTableList) {
            AppTableDto appTableDto = this.toDto(appTable);
            appTableDto.setFieldArr(tableFieldMap.get(appTableDto.getId()));
            resList.add(appTableDto);
        }
        return resList;
    }

    @Override
    public void saveOrUpdate(AppTableDto appTableDto) {
        dbTableOperatorService.createTable(appTableDto);
        AppTable appTable = this.toEntity(appTableDto);
        if(StringUtils.isEmpty(appTable.getId())){
            appTable.setId(ContextUtil.nextID());
        }
        this.saveOrUpdate(appTable);
        List<AppTableFieldDto> fieldArr = appTableDto.getFieldArr();
        this.refreshSort(fieldArr);
        for (AppTableFieldDto fieldDto : fieldArr) {
            if(fieldDto.getDelete() && fieldDto.getId() != null){
                appTableFieldService.deleteById(fieldDto.getId());
                continue;
            }
            fieldDto.setFormId(appTableDto.getFormId());
            fieldDto.setTableId(appTable.getId());
            dbTableOperatorService.ifNotExitCreate(appTableDto,fieldDto);
            appTableFieldService.saveOrUpdateDto(fieldDto);
        }
    }

    /**
     * 刷新排序号
     * @param fieldArr
     */
    private void refreshSort(List<AppTableFieldDto> fieldArr) {
        long i = 0;
        for (AppTableFieldDto fieldDto : fieldArr) {
            fieldDto.setSortId(i++);
        }
    }

    @Override
    public AppTableDto getManTableByFormId(String formId) {
        AppTable mainTable = this.getMainTable(formId);
        AppTableDto appTableDto = toDto(mainTable);
        if(mainTable == null){
            return appTableDto;
        }
        appTableDto.setFieldIndex(appIndexManager.getNextFieldIndex(mainTable.getId()));
        List<AppTableFieldDto> fieldDtoList = appTableFieldService.getByTableId(mainTable.getId());
        appTableDto.setFieldArr(fieldDtoList);
        return appTableDto;
    }

    /**
     * 获取表单的主表信息
     *
     * @param formId 表单iD
     * @return
     */
    private AppTable getMainTable(String formId) {
        List<AppTable> appTableList = appTableDao.createLambdaQuery().andEq(AppTable::getFormId, formId).andEq(AppTable::getTableType, TableTypeEnum.MAIN.getKey()).select();
        if(CollectionUtils.isEmpty(appTableList)){
            throw new RuntimeException("表单没有对应的底表信息,formId:" + formId);
        }else if(appTableList.size() > 1){
            throw new RuntimeException("表单没有对应的多个底表信息,formId:" + formId);
        }
        return appTableList.get(0);
    }

    @Override
    public List<AppTableDto> getSonTablesByFormId(String formId) {
        List<AppTable> sonTableList = appTableDao.createLambdaQuery().andEq(AppTable::getFormId, formId).andEq(AppTable::getTableType, TableTypeEnum.SON.getKey()).select();
        return appTableMapper.toDtos(sonTableList);
    }

    @Override
    public String getNextFieldIndex(String formId) {
        AppTableDto manTableByFormId = this.getManTableByFormId(formId);
        return appTableFieldService.getNextFieldIndex(formId);
    }
}
